using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace TopShooter
{
	public class PlayerEntity : Entity
	{
		static public PlayerEntity ActiveUser;

		public bool IsUserControlled;
		public Vector2 Velocity;

		private const float MoveAcceleration = 14000.0f;
		private const float MaxMoveSpeed = 1500.0f;
		protected float LinearDragFactor = 0.4f;
		protected Vector2 _movement;

		public PlayerEntity(bool isUserControlled)
			: base()
		{
			IsUserControlled = isUserControlled;
		}

		protected override void OnAddedToScene()
		{
			base.OnAddedToScene();

			OnLoadContent();
			Reset(false);

			if (IsUserControlled)
			{
				if (ActiveUser != null)
				{
					Health = ActiveUser.Health;
				}
				ActiveUser = this;
			}
		}
		protected override void OnRemovedFromScene(Scene scene)
		{
			InputHandler.Instance.NotifyListenerRemoved(this);
			base.OnRemovedFromScene(scene);
		}

		protected override void OnLoadContent()
		{
			_texture = Scene.Content.Load<Texture2D>("Entities/PlayerCircle");
			_origin = new Vector2(_texture.Width / 2.0f, _texture.Height / 2.0f);
			BoundingRadius = 1;
		}

		public void Reset(bool isNewLife)
		{
			if (!this.Scene.Entities.Contains(this))
				this.Scene.Entities.Add(this);
			Scale = 1;
			Velocity = Vector2.Zero;
		}

		public override void Update(GameTime gameTime)
		{
			MouseState mouseState = InputHandler.GetMouseState();

			System.Drawing.Size area = Game.Instance.ScreenSize;

			if (InputHandler.Instance.IsMouseOverScreen)
			{
				GetInput(gameTime);
			}
			else
			{ } // mouse is not overtop this window

			base.Update(gameTime);

			// Clear input.
			_movement = Vector2.Zero;
			
		}

		protected virtual void GetInput(GameTime gameTime)
		{
			if (!InputHandler.Instance.IsMouseOverScreen)
				return;

			// Get input state.
			GamePadState gamePadState = GamePad.GetState(PlayerIndex.One);
			KeyboardState keyboardState = InputHandler.GetKeyboardState();
			if (InputHandler.Instance.IsCtrlPressed)
				return;

			MouseState mouseState = InputHandler.GetMouseState();

			if (_movement.Length() < 0.5f)
				_movement = Vector2.Zero;

			// If any digital horizontal movement input is found, override the analog movement.

			if (keyboardState.IsKeyDown(Keys.Left))
			{
				_movement += new Vector2(-1f, 0);
			}
			if (keyboardState.IsKeyDown(Keys.Right))
			{
				_movement += new Vector2(1f, 0);
			}
			if (keyboardState.IsKeyDown(Keys.Up))
			{
				_movement += new Vector2(0, -1f);
			}
			if (keyboardState.IsKeyDown(Keys.Down))
			{
				_movement += new Vector2(0, 1f);
			}
			DetermineBoost(keyboardState, gameTime);
		}

		protected virtual void DetermineBoost(KeyboardState keyboardState, GameTime gameTime)
		{
			if (keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.Insert))
			{
				_timeWhenBoostExpires = (long)gameTime.TotalGameTime.TotalMilliseconds + 300;
			}
		}

		public override void ApplyPhysics(GameTime gameTime)
		{
			Vector2 prevLoc = Location;

			float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
			long timeNow = (long)gameTime.TotalGameTime.TotalMilliseconds;

			float boostFactor = 1;
			if (timeNow < _timeWhenBoostExpires)
				boostFactor = 1.5f;

			Velocity += boostFactor * _movement * MoveAcceleration * elapsed;

			// Apply Velocity.
			Location += Velocity * elapsed;
			Scene.UpdateVportPos();

			// Apply pseudo-drag horizontally.
			Velocity *= LinearDragFactor;

			if (Velocity.LengthSquared() < 0.0001f)
				Velocity = Vector2.Zero;
		}

		protected long _timeWhenBoostExpires;

		public override void Draw(SpriteBatch spriteBatch, Vector2 offset)
		{
			base.Draw(spriteBatch, offset);
		}
	}
}
